bitkeeper revision 1.1159.1.425 (419a4cf9VuB3gYuI3YPyE637uwwiRA)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 16 Nov 2004 18:54:49 +0000 (18:54 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 16 Nov 2004 18:54:49 +0000 (18:54 +0000)
Extend perdomain_pt to support multiple vcpus.
Add biglock.

16 files changed:
xen/arch/x86/dom0_ops.c
xen/arch/x86/domain.c
xen/arch/x86/memory.c
xen/arch/x86/shadow.c
xen/arch/x86/traps.c
xen/arch/x86/x86_32/mm.c
xen/arch/x86/x86_32/seg_fixup.c
xen/common/dom_mem_ops.c
xen/common/domain.c
xen/common/grant_table.c
xen/common/schedule.c
xen/include/asm-x86/config.h
xen/include/asm-x86/domain.h
xen/include/asm-x86/ldt.h
xen/include/asm-x86/processor.h
xen/include/xen/sched.h

index 0a32ba7b67702c015f768a23c042547825f22a22..9424f7c6e0ef768ce583489738f83078a803ed98 100644 (file)
@@ -128,11 +128,11 @@ void arch_getdomaininfo_ctxt(struct exec_domain *d, full_execution_context_t *c)
     c->ldt_base = d->mm.ldt_base;
     c->ldt_ents = d->mm.ldt_ents;
     c->gdt_ents = 0;
-    if ( GET_GDT_ADDRESS(d) == GDT_VIRT_START )
+    if ( GET_GDT_ADDRESS(d) == GDT_VIRT_START(d) )
     {
         for ( i = 0; i < 16; i++ )
             c->gdt_frames[i] = 
-                l1_pgentry_to_pagenr(d->mm.perdomain_pt[i]);
+                l1_pgentry_to_pagenr(d->mm.perdomain_ptes[i]);
         c->gdt_ents = GET_GDT_ENTRIES(d);
     }
     c->guestos_ss  = d->thread.guestos_ss;
index 86c6118ee662e67b4d889f9bbe3c71d703eb62d5..71cfd0a37eccfd1051abead8cc4da268dad30f82 100644 (file)
@@ -90,7 +90,7 @@ void continue_cpu_idle_loop(void)
 void startup_cpu_idle_loop(void)
 {
     /* Just some sanity to ensure that the scheduler is set up okay. */
-    ASSERT(current->id == IDLE_DOMAIN_ID);
+    ASSERT(current->domain->id == IDLE_DOMAIN_ID);
     domain_unpause_by_systemcontroller(current->domain);
     __enter_scheduler();
 
@@ -210,9 +210,9 @@ void machine_halt(void)
     __machine_halt(NULL);
 }
 
-void free_perdomain_pt(struct exec_domain *d)
+void free_perdomain_pt(struct domain *d)
 {
-    free_xenheap_page((unsigned long)d->mm.perdomain_pt);
+    free_xenheap_page((unsigned long)d->mm_perdomain_pt);
 }
 
 void arch_do_createdomain(struct exec_domain *ed)
@@ -227,10 +227,11 @@ void arch_do_createdomain(struct exec_domain *ed)
     machine_to_phys_mapping[virt_to_phys(d->shared_info) >> 
                            PAGE_SHIFT] = INVALID_P2M_ENTRY;
 
-    ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
-    memset(ed->mm.perdomain_pt, 0, PAGE_SIZE);
-    machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> 
+    d->mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
+    memset(d->mm_perdomain_pt, 0, PAGE_SIZE);
+    machine_to_phys_mapping[virt_to_phys(d->mm_perdomain_pt) >> 
                            PAGE_SHIFT] = INVALID_P2M_ENTRY;
+    ed->mm.perdomain_ptes = d->mm_perdomain_pt;
 }
 
 int arch_final_setup_guestos(struct exec_domain *d, full_execution_context_t *c)
@@ -761,7 +762,7 @@ int construct_dom0(struct domain *p,
     l2tab[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
         mk_l2_pgentry((unsigned long)l2start | __PAGE_HYPERVISOR);
     l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
-        mk_l2_pgentry(__pa(ed->mm.perdomain_pt) | __PAGE_HYPERVISOR);
+        mk_l2_pgentry(__pa(p->mm_perdomain_pt) | __PAGE_HYPERVISOR);
     ed->mm.pagetable = mk_pagetable((unsigned long)l2start);
 
     l2tab += l2_table_offset(dsi.v_start);
index e24aea10f8eacd5f6fbc521be49762b9df24a1cc..307c532d441f55bd715dc486dbff29f5f2eab66e 100644 (file)
@@ -206,12 +206,12 @@ static void __invalidate_shadow_ldt(struct exec_domain *d)
 
     for ( i = 16; i < 32; i++ )
     {
-        pfn = l1_pgentry_to_pagenr(d->mm.perdomain_pt[i]);
+        pfn = l1_pgentry_to_pagenr(d->mm.perdomain_ptes[i]);
         if ( pfn == 0 ) continue;
-        d->mm.perdomain_pt[i] = mk_l1_pgentry(0);
+        d->mm.perdomain_ptes[i] = mk_l1_pgentry(0);
         page = &frame_table[pfn];
         ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page);
-        ASSERT_PAGE_IS_DOMAIN(page, d);
+        ASSERT_PAGE_IS_DOMAIN(page, d->domain);
         put_page_and_type(page);
     }
 
@@ -263,7 +263,7 @@ int map_ldt_shadow_page(unsigned int off)
                                      d, PGT_ldt_page)) )
         return 0;
 
-    ed->mm.perdomain_pt[off + 16] = mk_l1_pgentry(l1e | _PAGE_RW);
+    ed->mm.perdomain_ptes[off + 16] = mk_l1_pgentry(l1e | _PAGE_RW);
     ed->mm.shadow_ldt_mapcnt++;
 
     return 1;
@@ -515,7 +515,7 @@ static int alloc_l2_table(struct pfn_info *page)
     pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
         mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR);
     pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
-        mk_l2_pgentry(__pa(page->u.inuse.domain->exec_domain[0]->mm.perdomain_pt) | 
+        mk_l2_pgentry(__pa(page->u.inuse.domain->mm_perdomain_pt) | 
                       __PAGE_HYPERVISOR);
 #endif
 
@@ -777,7 +777,7 @@ void put_page_type(struct pfn_info *page)
          * See domain.c:relinquish_list().
          */
         ASSERT((x & PGT_validated) || 
-               test_bit(DF_DYING, &page->u.inuse.domain->flags));
+               test_bit(DF_DYING, &page->u.inuse.domain->d_flags));
 
         if ( unlikely((nx & PGT_count_mask) == 0) )
         {
@@ -1296,10 +1296,14 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
     perfc_incrc(calls_to_mmu_update); 
     perfc_addc(num_page_updates, count);
 
+    LOCK_BIGLOCK(d);
+
     cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
 
-    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) )
+    if ( unlikely(!access_ok(VERIFY_READ, ureqs, count * sizeof(req))) ) {
+        UNLOCK_BIGLOCK(d);
         return -EFAULT;
+    }
 
     for ( i = 0; i < count; i++ )
     {
@@ -1460,6 +1464,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
     if ( unlikely(success_count != NULL) )
         put_user(count, success_count);
 
+    UNLOCK_BIGLOCK(d);
     return rc;
 }
 
@@ -1479,6 +1484,8 @@ int do_update_va_mapping(unsigned long page_nr,
     if ( unlikely(page_nr >= (HYPERVISOR_VIRT_START >> PAGE_SHIFT)) )
         return -EINVAL;
 
+    LOCK_BIGLOCK(d);
+
     cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
 
     /*
@@ -1529,6 +1536,8 @@ int do_update_va_mapping(unsigned long page_nr,
     if ( unlikely(deferred_ops & DOP_RELOAD_LDT) )
         (void)map_ldt_shadow_page(0);
     
+    UNLOCK_BIGLOCK(d);
+
     return err;
 }
 
@@ -1632,7 +1641,11 @@ void ptwr_flush(const int which)
 
     /* Ensure that there are no stale writable mappings in any TLB. */
     /* NB. INVLPG is a serialising instruction: flushes pending updates. */
+#if 0
     __flush_tlb_one(l1va); /* XXX Multi-CPU guests? */
+#else
+    flush_tlb_all();
+#endif
     PTWR_PRINTK("[%c] disconnected_l1va at %p now %08lx\n",
                 PTWR_PRINT_WHICH, ptep, pte);
 
@@ -1677,6 +1690,7 @@ void ptwr_flush(const int which)
                    (ENTRIES_PER_L1_PAGETABLE - i) * sizeof(l1_pgentry_t));
             unmap_domain_mem(pl1e);
             ptwr_info[cpu].ptinfo[which].l1va = 0;
+            UNLOCK_BIGLOCK(d);
             domain_crash();
         }
         
@@ -1721,7 +1735,9 @@ int ptwr_do_page_fault(unsigned long addr)
     l2_pgentry_t    *pl2e, nl2e;
     int              which, cpu = smp_processor_id();
     u32              l2_idx;
+    struct domain   *d = current->domain;
 
+    LOCK_BIGLOCK(d);
     /*
      * Attempt to read the PTE that maps the VA being accessed. By checking for
      * PDE validity in the L2 we avoid many expensive fixups in __get_user().
@@ -1729,7 +1745,10 @@ int ptwr_do_page_fault(unsigned long addr)
     if ( !(l2_pgentry_val(linear_l2_table[addr>>L2_PAGETABLE_SHIFT]) &
            _PAGE_PRESENT) ||
          __get_user(pte, (unsigned long *)&linear_pg_table[addr>>PAGE_SHIFT]) )
+    {
+        UNLOCK_BIGLOCK(d);
         return 0;
+    }
 
     pfn  = pte >> PAGE_SHIFT;
     page = &frame_table[pfn];
@@ -1737,12 +1756,18 @@ int ptwr_do_page_fault(unsigned long addr)
     /* We are looking only for read-only mappings of p.t. pages. */
     if ( ((pte & (_PAGE_RW | _PAGE_PRESENT)) != _PAGE_PRESENT) ||
          ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) )
+    {
+        UNLOCK_BIGLOCK(d);
         return 0;
+    }
     
     /* Get the L2 index at which this L1 p.t. is always mapped. */
     l2_idx = page->u.inuse.type_info & PGT_va_mask;
     if ( unlikely(l2_idx >= PGT_va_unknown) )
+    {
+        UNLOCK_BIGLOCK(d);
         domain_crash(); /* Urk! This L1 is mapped in multiple L2 slots! */
+    }
     l2_idx >>= PGT_va_shift;
         
     /*
@@ -1772,7 +1797,11 @@ int ptwr_do_page_fault(unsigned long addr)
     {
         nl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) & ~_PAGE_PRESENT);
         update_l2e(pl2e, *pl2e, nl2e);
+#if 0
         flush_tlb(); /* XXX Multi-CPU guests? */
+#else
+        flush_tlb_all();
+#endif
     }
     
     /* Temporarily map the L1 page, and make a copy of it. */
@@ -1793,9 +1822,12 @@ int ptwr_do_page_fault(unsigned long addr)
         /* Toss the writable pagetable state and crash. */
         unmap_domain_mem(ptwr_info[cpu].ptinfo[which].pl1e);
         ptwr_info[cpu].ptinfo[which].l1va = 0;
+        UNLOCK_BIGLOCK(d);
         domain_crash();
     }
     
+    UNLOCK_BIGLOCK(d);
+
     /* Maybe fall through to shadow mode to propagate writable L1. */
     return !current->mm.shadow_mode;
 }
@@ -1952,12 +1984,12 @@ void audit_domain(struct domain *d)
     struct list_head *list_ent;
     struct pfn_info *page;
 
-    if ( d != current )
+    if ( d != current->domain )
         domain_pause(d);
     synchronise_pagetables(~0UL);
 
     printk("pt base=%lx sh_info=%x\n",
-           pagetable_val(d->mm.pagetable)>>PAGE_SHIFT,
+           pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT,
            virt_to_page(d->shared_info)-frame_table);
            
     spin_lock(&d->page_alloc_lock);
@@ -2007,7 +2039,7 @@ void audit_domain(struct domain *d)
 
     /* PHASE 1 */
 
-    adjust(&frame_table[pagetable_val(d->mm.pagetable)>>PAGE_SHIFT], -1, 1);
+    adjust(&frame_table[pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT], -1, 1);
 
     list_ent = d->page_list.next;
     for ( i = 0; (list_ent != &d->page_list); i++ )
@@ -2251,11 +2283,11 @@ void audit_domain(struct domain *d)
 
     spin_unlock(&d->page_alloc_lock);
 
-    adjust(&frame_table[pagetable_val(d->mm.pagetable)>>PAGE_SHIFT], 1, 1);
+    adjust(&frame_table[pagetable_val(d->exec_domain[0]->mm.pagetable)>>PAGE_SHIFT], 1, 1);
 
     printk("Audit %d: Done. ctot=%d ttot=%d\n", d->id, ctot, ttot );
 
-    if ( d != current )
+    if ( d != current->domain )
         domain_unpause(d);
 }
 
index fb15881d52f766a5d5378d25261d26621e8697c1..4db46ecb81027788e7ab57a15d8b92f49c8de3b0 100644 (file)
@@ -473,7 +473,7 @@ unsigned long shadow_l2_table(
     spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
         mk_l2_pgentry((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
     spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
-        mk_l2_pgentry(__pa(frame_table[gpfn].u.inuse.domain->exec_domain[0]->mm.perdomain_pt) |
+        mk_l2_pgentry(__pa(frame_table[gpfn].u.inuse.domain->mm_perdomain_pt) |
                       __PAGE_HYPERVISOR);
 #endif
 
index cb057e9b6edc38a3b7f76c3aaf020ce6e62cde38..3908183c95b53d7465cad5f949e4674dab73128b 100644 (file)
@@ -346,6 +346,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
     struct domain *d = ed->domain;
     extern int map_ldt_shadow_page(unsigned int);
     int cpu = ed->processor;
+    int ret;
 
     __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
 
@@ -359,7 +360,9 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
              unlikely((addr >> L2_PAGETABLE_SHIFT) ==
                       ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
         {
+            LOCK_BIGLOCK(d);
             ptwr_flush(PTWR_PT_ACTIVE);
+            UNLOCK_BIGLOCK(d);
             return;
         }
 
@@ -373,16 +376,19 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code)
          (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) )
         return; /* Returns TRUE if fault was handled. */
 
-    if ( unlikely(addr >= LDT_VIRT_START) && 
-         (addr < (LDT_VIRT_START + (ed->mm.ldt_ents*LDT_ENTRY_SIZE))) )
+    if ( unlikely(addr >= LDT_VIRT_START(ed)) && 
+         (addr < (LDT_VIRT_START(ed) + (ed->mm.ldt_ents*LDT_ENTRY_SIZE))) )
     {
         /*
          * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
          * send the fault up to the guest OS to be handled.
          */
-        off  = addr - LDT_VIRT_START;
+        LOCK_BIGLOCK(d);
+        off  = addr - LDT_VIRT_START(ed);
         addr = ed->mm.ldt_base + off;
-        if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) )
+        ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
+        UNLOCK_BIGLOCK(d);
+        if ( likely(ret) )
             return; /* successfully copied the mapping */
     }
 
@@ -784,6 +790,8 @@ long do_set_trap_table(trap_info_t *traps)
     trap_info_t cur;
     trap_info_t *dst = current->thread.traps;
 
+    LOCK_BIGLOCK(current->domain);
+
     for ( ; ; )
     {
         if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
@@ -796,6 +804,8 @@ long do_set_trap_table(trap_info_t *traps)
         traps++;
     }
 
+    UNLOCK_BIGLOCK(current->domain);
+
     return 0;
 }
 
index 920bcca92a93c1d27552e49bb989139366df2973..65151324b41e9186e40e4afdb7d46e77e35440cd 100644 (file)
@@ -216,9 +216,9 @@ void destroy_gdt(struct exec_domain *ed)
 
     for ( i = 0; i < 16; i++ )
     {
-        if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_pt[i])) != 0 )
+        if ( (pfn = l1_pgentry_to_pagenr(ed->mm.perdomain_ptes[i])) != 0 )
             put_page_and_type(&frame_table[pfn]);
-        ed->mm.perdomain_pt[i] = mk_l1_pgentry(0);
+        ed->mm.perdomain_ptes[i] = mk_l1_pgentry(0);
     }
 }
 
@@ -272,10 +272,10 @@ long set_gdt(struct exec_domain *ed,
 
     /* Install the new GDT. */
     for ( i = 0; i < nr_pages; i++ )
-        ed->mm.perdomain_pt[i] =
+        ed->mm.perdomain_ptes[i] =
             mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
 
-    SET_GDT_ADDRESS(ed, GDT_VIRT_START);
+    SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed));
     SET_GDT_ENTRIES(ed, entries);
 
     return 0;
@@ -299,12 +299,16 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries)
     if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
         return -EFAULT;
 
+    LOCK_BIGLOCK(current->domain);
+
     if ( (ret = set_gdt(current, frames, entries)) == 0 )
     {
         local_flush_tlb();
         __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
     }
 
+    UNLOCK_BIGLOCK(current->domain);
+
     return ret;
 }
 
@@ -314,27 +318,36 @@ long do_update_descriptor(
 {
     unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2];
     struct pfn_info *page;
+    struct exec_domain *ed;
     long ret = -EINVAL;
 
     d[0] = word1;
     d[1] = word2;
 
-    if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) )
+    LOCK_BIGLOCK(current->domain);
+
+    if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) ) {
+        UNLOCK_BIGLOCK(current->domain);
         return -EINVAL;
+    }
 
     page = &frame_table[pfn];
-    if ( unlikely(!get_page(page, current->domain)) )
+    if ( unlikely(!get_page(page, current->domain)) ) {
+        UNLOCK_BIGLOCK(current->domain);
         return -EINVAL;
+    }
 
     /* Check if the given frame is in use in an unsafe context. */
     switch ( page->u.inuse.type_info & PGT_type_mask )
     {
     case PGT_gdt_page:
         /* Disallow updates of Xen-reserved descriptors in the current GDT. */
-        if ( (l1_pgentry_to_pagenr(current->mm.perdomain_pt[0]) == pfn) &&
-             (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
-             (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
-            goto out;
+        for_each_exec_domain(current->domain, ed) {
+            if ( (l1_pgentry_to_pagenr(ed->mm.perdomain_ptes[0]) == pfn) &&
+                 (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
+                 (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
+                goto out;
+        }
         if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
             goto out;
         break;
@@ -359,6 +372,9 @@ long do_update_descriptor(
 
  out:
     put_page(page);
+
+    UNLOCK_BIGLOCK(current->domain);
+
     return ret;
 }
 
index 996fd09e8a016ed707443f72e3cad7733df2703a..7e888c29f78a020b65ced8f51b9704712699d540 100644 (file)
@@ -113,7 +113,7 @@ int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit)
     /* Get base and check limit. */
     if ( ldt )
     {
-        table = (unsigned long *)LDT_VIRT_START;
+        table = (unsigned long *)LDT_VIRT_START(d);
         if ( idx >= d->mm.ldt_ents )
             goto fail;
     }
@@ -179,7 +179,7 @@ int fixup_seg(u16 seg, int positive_access)
     /* Get base and check limit. */
     if ( ldt )
     {
-        table = (unsigned long *)LDT_VIRT_START;
+        table = (unsigned long *)LDT_VIRT_START(d);
         if ( idx >= d->mm.ldt_ents )
         {
             DPRINTK("Segment %04x out of LDT range (%d)\n",
index b19aadd4a3a34c7dad0edb47f53ba7234b4054c7..84560343d25f30b230f60b6791a753c4fa5cb27b 100644 (file)
@@ -111,6 +111,8 @@ long do_dom_mem_op(unsigned int   op,
     else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
        return -ESRCH;
 
+    LOCK_BIGLOCK(d);
+
     switch ( op )
     {
     case MEMOP_increase_reservation:
@@ -127,5 +129,7 @@ long do_dom_mem_op(unsigned int   op,
     if ( unlikely(domid != DOMID_SELF) )
        put_domain(d);
 
+    UNLOCK_BIGLOCK(d);
+
     return rc;
 }
index ba54ae4d69a6fffdde73cb3c053780b202716f25..589995f4aca5ebf99076bc7a8c0bcf34ea92122a 100644 (file)
@@ -46,6 +46,8 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
 
     spin_lock_init(&d->time_lock);
 
+    spin_lock_init(&d->big_lock);
+
     spin_lock_init(&d->page_alloc_lock);
     INIT_LIST_HEAD(&d->page_list);
     INIT_LIST_HEAD(&d->xenpage_list);
@@ -216,7 +218,6 @@ unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
 void domain_destruct(struct domain *d)
 {
     struct domain **pd;
-    struct exec_domain *ed;
     atomic_t      old, new;
 
     if ( !test_bit(DF_DYING, &d->d_flags) )
@@ -244,8 +245,7 @@ void domain_destruct(struct domain *d)
     destroy_event_channels(d);
     grant_table_destroy(d);
 
-    for_each_exec_domain(d, ed)
-        free_perdomain_pt(ed);
+    free_perdomain_pt(d);
     free_xenheap_page((unsigned long)d->shared_info);
 
     free_domain_struct(d);
@@ -333,10 +333,7 @@ long do_boot_vcpu(unsigned long vcpu, full_execution_context_t *ctxt)
     memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread));
 
     /* arch_do_createdomain */
-    ed->mm.perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
-    memset(ed->mm.perdomain_pt, 0, PAGE_SIZE);
-    machine_to_phys_mapping[virt_to_phys(ed->mm.perdomain_pt) >> 
-                           PAGE_SHIFT] = INVALID_P2M_ENTRY;
+    ed->mm.perdomain_ptes = d->mm_perdomain_pt + (ed->eid << PDPT_VCPU_SHIFT);
 
     sched_add_domain(ed);
 
index 9da8866a8096a2171f7083956fd3d452adae668d..f9543e8b0a7e16a2cc72e977b291851cc4fdbb6b 100644 (file)
@@ -440,6 +440,8 @@ do_grant_table_op(
     if ( count > 512 )
         return -EINVAL;
 
+    LOCK_BIGLOCK(current->domain);
+
     switch ( cmd )
     {
     case GNTTABOP_map_grant_ref:
@@ -462,6 +464,8 @@ do_grant_table_op(
         break;
     }
 
+    UNLOCK_BIGLOCK(current->domain);
+
     return rc;
 }
 
index 86b51c07545934dd31cbd8d98eefcb2763a8cba1..0dd20dff9b26276b7f3877d77cf66e0f137be39d 100644 (file)
@@ -249,7 +249,7 @@ void domain_wake(struct exec_domain *d)
 /* Block the currently-executing domain until a pertinent event occurs. */
 long do_block(void)
 {
-    ASSERT(current->id != IDLE_DOMAIN_ID);
+    ASSERT(current->domain->id != IDLE_DOMAIN_ID);
     current->vcpu_info->evtchn_upcall_mask = 0;
     set_bit(EDF_BLOCKED, &current->ed_flags);
     TRACE_2D(TRC_SCHED_BLOCK, current->id, current);
@@ -374,8 +374,13 @@ void __enter_scheduler(void)
     task_slice_t        next_slice;
     s32                 r_time;     /* time for new dom to run */
 
-    cleanup_writable_pagetable(
-        prev->domain, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
+    if ( !is_idle_task(current->domain) )
+    {
+        LOCK_BIGLOCK(current->domain);
+        cleanup_writable_pagetable(
+            prev->domain, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
+        UNLOCK_BIGLOCK(current->domain);
+    }
 
     perfc_incrc(sched_run);
     
index a43afad7094b8e9f8a1f5a87059d7eee73627eac..6faf6bce98193d64682a75cf027ce6664df7ffa2 100644 (file)
@@ -215,10 +215,13 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
 extern unsigned long xenheap_phys_end; /* user-configurable */
 #endif
 
-#define GDT_VIRT_START        (PERDOMAIN_VIRT_START)
-#define GDT_VIRT_END          (GDT_VIRT_START + (64*1024))
-#define LDT_VIRT_START        (GDT_VIRT_END)
-#define LDT_VIRT_END          (LDT_VIRT_START + (64*1024))
+#define GDT_VIRT_START(ed)    (PERDOMAIN_VIRT_START + ((ed)->eid << PDPT_VCPU_VA_SHIFT))
+#define GDT_VIRT_END(ed)      (GDT_VIRT_START(ed) + (64*1024))
+#define LDT_VIRT_START(ed)    (PERDOMAIN_VIRT_START + (64*1024) + ((ed)->eid << PDPT_VCPU_VA_SHIFT))
+#define LDT_VIRT_END(ed)      (LDT_VIRT_START(ed) + (64*1024))
+
+#define PDPT_VCPU_SHIFT       5
+#define PDPT_VCPU_VA_SHIFT    (PDPT_VCPU_SHIFT + PAGE_SHIFT)
 
 #if defined(__x86_64__)
 #define ELFSIZE 64
index a0dd3e58c2abf6a3cc62c57a263348065662ee8b..729a14c8a1aa56de63ae8e61c17944e0bcaac301 100644 (file)
@@ -7,7 +7,7 @@ extern void arch_do_createdomain(struct exec_domain *d);
 extern int  arch_final_setup_guestos(
     struct exec_domain *d, full_execution_context_t *c);
 
-extern void free_perdomain_pt(struct exec_domain *d);
+extern void free_perdomain_pt(struct domain *d);
 
 extern void domain_relinquish_memory(struct domain *d);
 
index 7546d2b0da64df7408dd6c41739fd259d1df509c..84c456120c8171c9661c8c8c66e87af3c31acdc2 100644 (file)
@@ -17,9 +17,9 @@ static inline void load_LDT(struct exec_domain *p)
     {
         cpu = smp_processor_id();
         desc = (struct desc_struct *)GET_GDT_ADDRESS(p) + __LDT(cpu);
-        desc->a = ((LDT_VIRT_START&0xffff)<<16) | (ents*8-1);
-        desc->b = (LDT_VIRT_START&(0xff<<24)) | 0x8200 |
-            ((LDT_VIRT_START&0xff0000)>>16);
+        desc->a = ((LDT_VIRT_START(p)&0xffff)<<16) | (ents*8-1);
+        desc->b = (LDT_VIRT_START(p)&(0xff<<24)) | 0x8200 |
+            ((LDT_VIRT_START(p)&0xff0000)>>16);
         __asm__ __volatile__ ( "lldt %%ax" : : "a" (__LDT(cpu)<<3) );
     }
 }
index 38110b94ee4d72c4f253d0e3632a91e0d4aec9ef..2082446a71869aa9d5deb5eba8f392a418bd4071 100644 (file)
@@ -364,7 +364,7 @@ struct mm_struct {
      * Every domain has a L1 pagetable of its own. Per-domain mappings
      * are put in this table (eg. the current GDT is mapped here).
      */
-    l1_pgentry_t *perdomain_pt;
+    l1_pgentry_t *perdomain_ptes;
     pagetable_t  pagetable;
 
     /* shadow mode status and controls */
@@ -410,8 +410,8 @@ static inline void write_ptbase(struct mm_struct *mm)
 
 #define IDLE0_MM                                                    \
 {                                                                   \
-    perdomain_pt: 0,                                                \
-    pagetable:   mk_pagetable(__pa(idle_pg_table))                  \
+    perdomain_ptes: 0,                                              \
+    pagetable:      mk_pagetable(__pa(idle_pg_table))               \
 }
 
 /* Convenient accessor for mm.gdt. */
index d33806b326dccd7c16862f26654f4bbc34dea7b5..991718654700e438f77dbca94b21f72d24a976f6 100644 (file)
@@ -108,6 +108,14 @@ struct exec_domain
 
 };
 
+#if 01
+#define LOCK_BIGLOCK(_d) spin_lock(&(_d)->big_lock)
+#define UNLOCK_BIGLOCK(_d) spin_unlock(&(_d)->big_lock)
+#else
+#define LOCK_BIGLOCK(_d) (void)(_d)
+#define UNLOCK_BIGLOCK(_d)
+#endif
+
 struct domain {
     domid_t          id;
     s_time_t         create_time;
@@ -115,6 +123,10 @@ struct domain {
     shared_info_t   *shared_info;     /* shared data area */
     spinlock_t       time_lock;
 
+    spinlock_t       big_lock;
+
+    l1_pgentry_t    *mm_perdomain_pt;
+
     spinlock_t       page_alloc_lock; /* protects all the following fields  */
     struct list_head page_list;       /* linked list, of size tot_pages     */
     struct list_head xenpage_list;    /* linked list, of size xenheap_pages */